home *** CD-ROM | disk | FTP | other *** search
- /*
- File: ODMath.cpp
-
- Contains: Math routines (fixed-point and wide) for OpenDoc.
-
- Owned by: Jens Alfke
- Written by: Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good,
- Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink,
- Chris Yerga
-
- Copyright: © 1987 - 1995 by Apple Computer, Inc., all rights reserved.
-
- Notes:
- The PowerPC definitions of many of these functions are already built
- into the Mac OS, so they are compiled here only for 68k. Likewise,
- the 68k definitions of some of these functions are coded in assembly
- language in ODMathM.a, and they are compiled here only for PowerPC.
-
- To Do:
- In Progress:
-
- */
-
-
- #ifndef _ODMATH_
- #include "ODMath.h"
- #endif
-
- #ifndef __FIXMATH__
- #include <FixMath.h>
- #endif
-
-
- //=============================================================================
- // Constants
- //=============================================================================
-
-
- #define longSize 32
- #define wideSize 64
-
- #define highBit ((ODULong) 0x80000000)
-
-
- //=============================================================================
- // Wide Math For Non-PowerPC
- //=============================================================================
-
-
- #if !defined(powerc) && !defined(__powerc)
-
-
- ODFixed lastSinCosAngle = 0; // Globals used in .a file
- ODFract lastSine = 0,
- lastCosine = kODFract1;
-
-
- // Wide math routines are already in the OS on Power Macs.
-
-
- ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
- {
- if (a->hi > b->hi) return 1;
- if (a->hi < b->hi) return -1;
- if (a->lo > b->lo) return 1;
- if (a->lo < b->lo) return -1;
- return 0;
- }
-
-
- ODWide *
- ODWideNegate(register ODWide *dst)
- {
- if (dst->lo) {
- dst->lo = -dst->lo;
- dst->hi = ~dst->hi;
- } else
- dst->hi = -dst->hi;
- return dst;
- }
-
-
- /* Shift a ODWide to the right (shift > 0) or left (shift < 0) */
- ODWide *
- ODWideShift(register ODWide *src, register ODSShort shift)
- {
- register long x = src->hi, y = src->lo;
- if (shift > 0)
- if (shift >= longSize)
- { src->hi = -(x < 0);
- src->lo = x >> shift - longSize;
- if (shift == longSize && y < 0 || x << wideSize - shift < 0)
- ++src->lo || ++src->hi;
- }
- else
- { src->hi = x >> shift;
- src->lo = x << longSize - shift | (unsigned long)y >> shift;
- if (y << longSize - shift < 0)
- ++src->lo || ++src->hi;
- }
- else if ( (shift = -shift) != 0 )
- if (shift >= longSize)
- { src->hi = y << shift - longSize;
- src->lo = 0;
- }
- else
- { src->hi = x << shift | (unsigned long)y >> longSize - shift;
- src->lo = y << shift;
- }
- return src;
- }
-
-
- ODWide *
- ODWideAdd(register ODWide *dst, register const ODWide *src)
- {
- dst->lo += src->lo;
- if (dst->lo < src->lo)
- dst->hi += src->hi + 1;
- else
- dst->hi += src->hi;
- return dst;
- }
-
-
- ODWide *
- ODWideSubtract(register ODWide *dst, register const ODWide *src)
- {
- if (dst->lo < src->lo)
- dst->hi -= src->hi + 1;
- else
- dst->hi -= src->hi;
- dst->lo -= src->lo;
- return dst;
- }
-
-
- // ODWideMultiply and ODWideDivide are in ODMathM.a
-
-
-
- //=============================================================================
- // Wide Math & Bit-Twiddling For PowerPC
- //=============================================================================
-
-
- #else /*powerc*/
-
-
- ODSShort
- ODFirstBit( ODSLong x ) // JPA: I wrote this from scratch
- {
- ODSShort bit = 0;
-
- if (x == 0)
- return -1;
-
- if (x >= 1UL << 16)
- bit += 16, x >>= 16;
- if (x >= 1UL << 8)
- bit += 8, x >>= 8;
- if (x >= 1UL << 4)
- bit += 4, x >>= 4;
- if (x >= 1UL << 2)
- bit += 2, x >>= 2;
- if (x >= 1UL << 1)
- bit += 1;
- return bit;
- }
-
- #undef ODWideCompare
- ODSShort ODWideCompare(const ODWide *a, const ODWide *b)
- {
- return (ODSShort) WideCompare(a,b);
- }
-
- #undef ODWideNegate
- ODWide * ODWideNegate(register ODWide *dst)
- {
- return (ODWide*) WideNegate(dst);
- }
-
- #undef ODWideShift
- ODWide * ODWideShift(register ODWide *src, register ODSShort shift)
- {
- return (ODWide*) WideShift(src,(long)shift);
- }
-
- #undef ODWideAdd
- ODWide * ODWideAdd(register ODWide *dst, register const ODWide *src)
- {
- return (ODWide*) WideAdd(dst,src);
- }
-
- #undef ODWideSubtract
- ODWide * ODWideSubtract(register ODWide *dst, register const ODWide *src)
- {
- return (ODWide*) WideSubtract(dst,src);
- }
-
- #undef ODWideDivide
- ODSLong ODWideDivide( register const ODWide *dividend,
- ODSLong divisor, ODSLong *remainder)
- {
- return (ODSLong) WideDivide(dividend,divisor,remainder);
- }
-
- #undef ODWideSquareRoot
- ODULong ODWideSquareRoot(register const ODWide *src)
- {
- return (ODULong) WideSquareRoot(src);
- }
-
- ODFract
- ODFractSinCos( ODFixed angle, ODFract *cos )
- {
- // I have no idea whether FracSin and FracCos are native ... if not,
- // this will be much slower than it could be. But is this every going
- // to be a bottleneck? [OPTIMIZATION]
-
- if( cos )
- *cos = FracCos(angle);
- return FracSin(angle);
- }
-
- #endif /*powerc*/
-